import json
import os

from jinja2 import FileSystemLoader, Environment
from distutils.sysconfig import get_python_lib
from zeus.operation_service.app.proxy.asset import AssetProxy
from zeus.operation_service.app.core.framework.task.task_result.result_generator.health_check.report_generator import ReportGenerator


class ItemHealthCheckGenerator(ReportGenerator):

    def __init__(self, report_path):
        super().__init__(report_path)
        self._check_item_stat = list()
        self.item_template = "html/ItemHealthCheckTemplate.html"
        self.summary_template = "html/ItemSummary.html"
        self.templates_path = os.path.join(get_python_lib(), "zeus", "operation_service", "templates")

    def parse_raw_data(self, raw_data):
        result = dict()

        for asset_id, asset_result_set in raw_data.items():
            asset_result_by_check_item = dict()
            for task_name_and_host, asset_result in asset_result_set.items():
                for check_id, check_item_result in asset_result.items():
                    check_item_result_by_host = dict()
                    check_item_result_by_host["name"] = task_name_and_host.split("@_@")[0]
                    check_item_result_by_host["ip"] = task_name_and_host.split("@_@")[1]
                    check_item_result_by_host["result"] = check_item_result
                    if check_id not in asset_result_by_check_item.keys():
                        asset_result_by_check_item[check_id] = list()
                    asset_result_by_check_item[check_id].append(check_item_result_by_host)

            result[asset_id] = asset_result_by_check_item

        return result

    def get_single_item_data(self, asset_id, check_id, host_info):
        check_item_obj = AssetProxy().get_asset_item_by_item_path(asset_id, check_id)
        check_item_detail = json.loads(check_item_obj.item_detail)
        check_item_info = dict()
        check_item_info["name"] = check_item_detail.get("description").get("des_zh").get("@value")
        importance_map = {"0": "Very important", "1": "Important", "2": "General"}
        stat_map = {"0": "passing", "1": "notPassed", "2": "notPassed", "3": "notPassed",
                    "4": "executionFailed", "5": "executionTimeout", "990": "skipped"}
        nodeHealthStatistics = {"total": 0, "passing": 0, "notPassed": 0, "executionFailed": 0, "executionTimeout": 0,
                                "skipped": 0}
        check_item_info["importance"] = importance_map[
            check_item_detail.get("importance", {"@value": "1"}).get("@value", "1")]
        check_item_info["taskInfo"] = check_item_detail.get("details").get("detail_zh").get("@value")
        health_check_info = list()
        for host in host_info:
            health_check_node_item_info = dict()

            host_result = json.loads(host['result'])[0]
            nodeHealthStatistics[stat_map[str(host_result["ErrLevel"])]] += 1
            nodeHealthStatistics["total"] += 1

            health_check_node_item_info["name"] = host["name"]
            health_check_node_item_info["ip"] = host["ip"]
            health_check_node_item_info["errLevel"] = host_result["ErrLevel"]

            health_check_node_item_info["status"] = stat_map[str(host_result["ErrLevel"])]
            health_check_node_item_info["importance"] = check_item_info["importance"]

            check_item_err_info = check_item_detail["ErrInfo"]
            if check_item_err_info and check_item_err_info.get(str(host_result['ErrInfo'])):
                health_check_node_item_info["description"] = check_item_err_info.get(host_result['ErrInfo']).get(
                    "value_zh").get("@value")
            else:
                health_check_node_item_info["description"] = host_result["ErrInfo"]

            check_item_sug_info = check_item_detail["Suggest"]
            if check_item_sug_info and check_item_sug_info.get(host_result["Suggest"]):
                health_check_node_item_info["suggestion"] = check_item_sug_info.get(host_result["Suggest"]).get(
                    "value_zh").get("@value")
            else:
                health_check_node_item_info["suggestion"] = host_result["Suggest"]

            health_check_node_item_info["isFirst"] = False
            health_check_node_item_info["rowspan"] = 1
            health_check_info.append(health_check_node_item_info)
        sort_map = {0: 3, 1: 1, 2: 1, 3: 1, 4: 2, 5: 2}  # 通过ErrLevel排序
        health_check_info = sorted(health_check_info,
                                   key=lambda e: (
                                       sort_map[e.__getitem__('errLevel')], hash(e.__getitem__('suggestion'))))
        nodeHealthStatistics.update((k, str(v)) for k, v in nodeHealthStatistics.items())
        return check_item_info, health_check_info, nodeHealthStatistics

    def prepare_summary_data(self, asset_id, check_id, check_item_info, nodeHealthStatistics):
        check_item_info_for_summary = dict()
        check_item_info_for_summary["name"] = check_item_info.get("name")
        check_item_info_for_summary["importance"] = check_item_info.get("importance")
        check_item_info_for_summary.update(nodeHealthStatistics)
        check_item_info_for_summary["checkId"] = check_id
        asset = AssetProxy().get_asset_by_asset_id(asset_id)
        check_item_info_for_summary["asset_name"] = json.loads(asset.name).get("zh")
        check_item_info_for_summary["asset_id"] = asset_id

        if nodeHealthStatistics["total"] == nodeHealthStatistics["passing"]:
            check_item_info_for_summary["status"] = "passing"
        elif int(nodeHealthStatistics["passing"]) > 0:
            check_item_info_for_summary["status"] = "partially.passed"
        elif int(nodeHealthStatistics["notPassed"]) > 0:
            check_item_info_for_summary["status"] = "not.passed"
        else:
            check_item_info_for_summary["status"] = "execution.failed"

        self._check_item_stat.append(check_item_info_for_summary)

    def get_summary_data(self):
        summary_report_info = dict()
        item_health_statistics = {"total": 0, "passing": 0, "not.passed": 0, "execution.failed": 0,
                                  "partially.passed": 0}
        for check_item in self._check_item_stat:
            item_health_statistics[check_item["status"]] += 1
            item_health_statistics["total"] += 1

        sort_map = {"passing": 3, "partially.passed": 2, "not.passed": 1, "execution.failed": 0}  # 通过status排序
        self._check_item_stat = sorted(self._check_item_stat,
                                   key=lambda e: (
                                   sort_map[e.__getitem__('status')], e.__getitem__('checkId')))
        return summary_report_info, item_health_statistics

    def generate_report(self, raw_data):
        result = self.parse_raw_data(raw_data)
        loader = FileSystemLoader(self.templates_path)
        env = Environment(loader=loader)
        item_path = os.path.join(self._report_path, "check_items")
        summary_path = self._report_path

        if not os.path.exists(item_path):
            os.makedirs(item_path)

        item_template = env.get_template(self.item_template)
        for asset_id, check_item_set in result.items():
            for check_id, host_info in check_item_set.items():
                check_item_info, health_check_info, nodeHealthStatistics = self.get_single_item_data(asset_id, check_id, host_info)
                self.prepare_summary_data(asset_id, check_id, check_item_info, nodeHealthStatistics)

                item_template.stream(resourceBundle=self.get_resource_bundle(), checkItemInfo=check_item_info,
                            healthcheckInfo=health_check_info, nodeHealthStatistics=nodeHealthStatistics).dump(
                    f"{item_path}/result_{asset_id}_{check_id}.html")

        summary_report_info, itemHealthStatistics = self.get_summary_data()
        summary_template = env.get_template(self.summary_template)
        summary_template.stream(summaryReportInfo=summary_report_info, resourceBundle=self.get_resource_bundle(), checkItemInfo=self._check_item_stat, itemHealthStatistics=itemHealthStatistics).dump(
                    f"{summary_path}/ItemSummary.html")
